package pl.kosmowska.ewelina.client.app.activity;


import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import pl.kosmowska.ewelina.client.Constants;
import pl.kosmowska.ewelina.client.ViewMessages;
import pl.kosmowska.ewelina.client.app.ClientFactory;
import pl.kosmowska.ewelina.client.app.activity.places.OutcomePlace;
import pl.kosmowska.ewelina.client.app.activity.places.SavingsEditPlace;
import pl.kosmowska.ewelina.client.app.activity.places.SavingsPlace;
import pl.kosmowska.ewelina.client.app.activity.places.SignInPlace;
import pl.kosmowska.ewelina.client.app.requestfactory.OutcomeDataRequest;
import pl.kosmowska.ewelina.client.app.requestfactory.SavingsDataRequest;
import pl.kosmowska.ewelina.client.app.requestfactory.dto.OutcomeDataProxy;
import pl.kosmowska.ewelina.client.app.requestfactory.dto.SavingsDataProxy;
import pl.kosmowska.ewelina.client.app.user.AuthEvent;
import pl.kosmowska.ewelina.client.app.user.AuthEvent.Auth;
import pl.kosmowska.ewelina.client.app.user.AuthEventHandler;
import pl.kosmowska.ewelina.client.views.SavingsEditView;

import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.ServerFailure;

public class SavingsEditActivity extends AbstractActivity implements SavingsEditView.Presenter {

	private SavingsEditView view;

	private ClientFactory clientFactory;


	private SavingsDataProxy savingsData;

	private EntityProxyId<SavingsDataProxy> savingsDataId;

	private OutcomeDataProxy outcomeDataProxy;

	private OutcomeDataRequest outcomeRequest;

	SavingsDataRequest savingsRequest;

	public SavingsEditActivity(SavingsEditPlace place, ClientFactory clientFactory) {
		this.savingsData = place.getSavingsData();
		this.savingsDataId = place.getSavingsDataId();
		this.clientFactory = clientFactory;
		this.outcomeDataProxy= place.getOutcomeDataProxy();
		this.outcomeRequest=place.getOutcomeRequest();
		savingsRequest = clientFactory.getRequestFactory().getSavingsDataRequest();

	}


	@Override
	public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
		view = clientFactory.getSavingsEditView();
		view.setPresenter(this);
		view.setOutcomeProxy(outcomeDataProxy);

		if (savingsDataId != null) { 
			getSavingsData(savingsDataId);

		} else {
			view.setData(savingsData);
			startView();
		}

		containerWidget.setWidget(view.asWidget());

	}

	private void initAuthorisationForView() {
		if (view.isAlreadyInit() == false) {
			clientFactory.getEventBus().addHandler(AuthEvent.TYPE, new AuthEventHandler() {
				public void onAuthEvent(AuthEvent event) {
					Auth e = event.getAuthEvent();
					if (e == Auth.LOGGEDIN) {
						view.reInitView();
					} else if (e == Auth.LOGGEDOUT) {
						goTo(new SignInPlace());
					}
				}
			});
		}
		view.setAlreadyInit(true);
	}

	private void startView() {
		if (clientFactory.getIsLoggedIn() == null) {
			// wait for login event b/c hasn't happened yet
		} else if (clientFactory.getIsLoggedIn() == true) {
			view.reInitView();
		} else if (clientFactory.getIsLoggedIn() == false) { 
			goTo(new SignInPlace());
		}	
	}


	private void getSavingsData(EntityProxyId<SavingsDataProxy> savingsDataId) {
		Request<SavingsDataProxy> request = clientFactory.getRequestFactory().getSavingsDataRequest().find(savingsDataId);
		request.fire(new Receiver<SavingsDataProxy>() {
			public void onSuccess(SavingsDataProxy savingsData) {
				setData(savingsData);
				view.setData(savingsData);
				startView();
			}

			public void onFailure(ServerFailure error) {
				view.showMessage(ViewMessages.ERROR_TIME_OUT);
				super.onFailure(error);
			}
		});

	}
	private void setData(SavingsDataProxy savingsData) {
		this.savingsData = savingsData;

	}


	public void goTo(Place place) {
		clientFactory.getPlaceController().goTo(place);
	}

	@Override
	public void saveSavingsData(String name, float value, Date startDate,
			Date endDate, List<OutcomeDataProxy> outcomeDataList) {
		// is it create or edit
		SavingsDataProxy data = null;
		if (savingsData == null) { // insert|create
			data = savingsRequest.create(SavingsDataProxy.class);

		} else { // update|edit
			data = savingsRequest.edit(savingsData);
		}

		// persist these
		data.setName(name);
		data.setValue(value);
		data.setStartDate(startDate);
		data.setEndDate(endDate);


		savingsRequest.persist(data, outcomeDataList).fire(new Receiver<SavingsDataProxy>() {
			public void onSuccess(SavingsDataProxy savingsData) {
				if(outcomeDataProxy==null)
					clientFactory.getPlaceController().goTo(new SavingsPlace());
				else
					saveOutcome(savingsData);
			}
			public void onFailure(ServerFailure error) {
				view.showMessage(ViewMessages.ERROR_ON_PERSIST);
				super.onFailure(error);
			}
		}); 

	}

	@Override
	public void generateOutcomeList(String name, float value,
			Date startDate, Date endDate) {
		List<OutcomeDataProxy> outcomeDataList = new ArrayList<OutcomeDataProxy>();
		int periodCount=0;
		Date date = new Date(startDate.getTime());
		while (date.getTime()<=endDate.getTime()){
			periodCount++;
			if (date.getMonth()==11)
				date.setYear(date.getYear()+1);	
			date.setMonth((date.getMonth()+1)%12);
		}

		if (periodCount==0){
			view.showMessage(ViewMessages.ERROR_WRONG_INPUT);
			return;
		}
		float installmentValue=-round(value/(float)periodCount);

		outcomeDataList.clear();
		date = new Date(startDate.getTime());
		while (date.getTime()<=endDate.getTime()){
			OutcomeDataProxy outcomeData = savingsRequest.create(OutcomeDataProxy.class);
			outcomeData.setName(name);
			outcomeData.setValue(installmentValue);
			outcomeData.setCategory(Constants.SAVINGS_CATEGORY);
			outcomeData.setDate(new Date(date.getTime()));
			outcomeData.setPriority(Constants.OUTCOME_PRIORITY_HIGH);
			outcomeData.setMultiple(true);
			outcomeData.setRepeatInterval(Constants.OUTCOME_FREQUENCY_MONTH);
			outcomeData.setRepeatEndDate(endDate);
			outcomeDataList.add(outcomeData);
			if (date.getMonth()==11)
				date.setYear(date.getYear()+1);	
			date.setMonth((date.getMonth()+1)%12);

		}
		view.setOutcomeDataList(outcomeDataList);
		view.showGrid();
	}

	private float round (double val)
	{
		double exp = Math.pow(10, 2);
		double rounded = val * exp;
		rounded = Math.round(rounded);
		return (float)(rounded / exp);
	}



	public void saveOutcome(SavingsDataProxy savingsData) {
		outcomeDataProxy.setSponsorKey(savingsData.getId());
		outcomeRequest.persist(outcomeDataProxy).fire(new Receiver<OutcomeDataProxy>() {
			public void onSuccess(OutcomeDataProxy walletData) {
				clientFactory.getPlaceController().goTo(new OutcomePlace());

			}
			public void onFailure(ServerFailure error) {
				view.showMessage("B\u0142\u0105d zapisu. Spr\u00F3buj ponownie!");
				super.onFailure(error);
			}
		});
	}


	@Override
	public void goToSavingsPlace() {
		goTo(new SavingsPlace());
	}


}
